/*
 * @Author: zyk
 * @Date: 2020-10-23 10:06:53
 * @LastEditTime: 2020-10-23 20:41:29
 * @LastEditors: Please set LastEditors
 * @Description: Collectors工具类的使用
 * @FilePath: \javaCode\java8newPro\streamProgram\StreamCollect.java
 */
package java8newPro.streamProgram;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamCollect {

    // 将stream转化为各种集合
    public static void toCollectionTest(List<String> list) {
        LinkedList<String> li = list.stream().collect(Collectors.toCollection(LinkedList::new));
        Set<String> ss = list.stream().collect(Collectors.toSet());
        List<String> ll = list.stream().collect(Collectors.toList());

    }

    // joining的目的是将流中的元素全部以字符序列的方式连接到一起，可以指定连接符，甚至是结果的前后缀。
    public static void joiningTest(List<String> list){
        // 无参方法
        String s = list.stream().collect(Collectors.joining());
        System.out.println(s);
        // 指定连接符
        String ss = list.stream().collect(Collectors.joining("-"));
        System.out.println(ss);
        // 指定连接符和前后缀
        String sss = list.stream().collect(Collectors.joining("-", "S", "E"));
        System.out.println(sss);
        /* 1234567891101212121121asdaa3e3e3e2321eew
            123-456-789-1101-212121121-asdaa-3e3e3e-2321eew
            S123-456-789-1101-212121121-asdaa-3e3e3e-2321eewE */
    }

    // mapping 这个映射是首先对流中的每个元素进行映射，即类型转换，然后再将新元素以给定的Collector进行归纳。
    public static void mappingTest(List<String> list) {
        List<Integer> l1 = list.stream().limit(5).collect(Collectors.mapping(Integer::valueOf, Collectors.toList()));
        // List<Integer> ll = list.stream().limit(5).collect(Collectors.mapping(Integer::valueOf,Collectors.toList()));

    }

    // collectingAndThen 该方法是在归纳动作结束之后，对归纳的结果进行再处理。
    public static void collectingAndThenTest(List<String> list) {
        int length = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), e->e.size()));
        System.out.println(length);
    }

    // counting 用于计数
    public static void countingTest(List<String> list){
        long size = list.stream().collect(Collectors.counting());
        System.out.println(size);
    }
    
    // minBy/maxBy 生成一个用于获取最小/最大值的Optional结果的Collector
    public static void maxMyAndMinByTest(List<String> list) {
        System.out.println(list.stream().collect(Collectors.maxBy((a,b)->a.length()-b.length())));
        System.out.println(list.stream().collect(Collectors.minBy((a,b)->a.length()-b.length())));
    }

    // summingInt/summingLong/summingDouble 生成一个用于求元素和的collector，首先将元素转换类型，然后再求和
    public static void summingTest(List<String> list) {
        int i = list.stream().collect(Collectors.summingInt(Integer::valueOf));
        long l = list.stream().collect(Collectors.summingLong(Long::valueOf));
        double d = list.stream().collect(Collectors.summingDouble(Double::valueOf));
        System.out.println(i+" "+l+" "+d);
    }

    public static void reducingTest(List<String> list){
        System.out.println(list.stream().limit(4).map(String::length).collect(Collectors.reducing(Integer::sum)));
        System.out.println(list.stream().limit(3).map(String::length).collect(Collectors.reducing(0, Integer::sum)));
        System.out.println(list.stream().limit(4).collect(Collectors.reducing(0,String::length,Integer::sum)));
    }

    // averagingInt/averagingLong/averagDouble 生成一个用于求元素平均值的collector，首先通过参数将元素转换为指定的
    // 类型。参数的作用就是将元素转换为指定的类型，求平均值涉及到除法操作，结果一律为Double类型
    public static void averagingTest(List<String> list) {
        double i = list.stream().collect(Collectors.averagingInt(Integer::valueOf));
        double l = list.stream().collect(Collectors.averagingLong(Long::valueOf));
        double d = list.stream().collect(Collectors.averagingDouble(Double::valueOf));
        System.out.println(i+" "+l+" "+d);
    }

    // groupingBy 这个方法用于生成一个拥有分组功能的Collector,他也有三个重载方法
    public static void groupingByTest(List<String> list) {
        Map<Integer, List<String>> s = list.stream().collect(Collectors.groupingBy(String::length));
        Map<Integer,List<String>> ss = list.stream().collect(Collectors.groupingBy(String::length, Collectors.toList()));
        Map<Integer,Set<String>> sss = list.stream().collect(Collectors.groupingBy(String::length,HashMap::new,Collectors.toSet()));
        System.out.println(s.toString() + "\n" + ss.toString() + "\n" + sss.toString());
    }

    // toMap方法根据给定的键生成器和值生成器生成的键和值保存到一个map中返回，键和值的生成都依赖于元素，可以指定出现重复
    // 键时的处理方法和保存结果的map
    public static void toMapTest(List<String> list) {
        Map<String,String> map = list.stream().collect(Collectors.toMap(e->e.substring(0, 1), e -> e));
        Map<String,String> map1 = list.stream().collect(Collectors.toMap(e->e.substring(0,1), e->e,(a,b)->b));
        Map<String,String> map2 = list.stream().collect(Collectors.toMap(e -> e.substring(0,1),e->e,(a,b)-> b,HashMap::new));
        System.out.println(map.toString() + "\n" + map1.toString() + "\n" + map2.toString());
    }


    public static void main(String[] args) {
        List<String> list = Arrays.asList("one","two","three","four");

        
    }
}
